﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Drawing.Design;

namespace GameEditor.Common
{
	[Editor(typeof(DynamicValueTypeEditor), typeof(UITypeEditor))]
	[TypeConverter(typeof(ExpandableObjectConverter))]
    public abstract class DynamicValue : ICloneable
    {
        public abstract object Clone();

    }


    
	public class DynamicValueTypeEditor : UITypeEditor
	{
		public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
        {
	        if (context != null && context.Instance != null)
		        return UITypeEditorEditStyle.Modal;
	        return UITypeEditorEditStyle.None;
        }
        public override Object EditValue(ITypeDescriptorContext context, IServiceProvider provider, Object value)
        {
            DynamicValue v = context.PropertyDescriptor.GetValue(context.Instance) as DynamicValue;

            GameEditor.Common.Dialogs.ShowDynamicValueDialog(null, ref v);


	        return v;
        }
	};



    public class FixedValue : DynamicValue
    {
        [NotifyParentProperty(true)]
        [DisplayName("值")]
        public float Value { get; set; }
        public FixedValue(float v)
        {
            this.Value = v;
        }
        public override string ToString()
        {
            return Value.ToString();
        }
        public static readonly FixedValue One = new FixedValue(1);
        public static readonly FixedValue Zero = new FixedValue(0);

        public override object Clone()
        {
            return new FixedValue(Value);
        }
    }
    public class RandomValue : DynamicValue
    {
        [NotifyParentProperty(true)]
        [DisplayName("平均值")]
        public float Base { get; set; }


        [DisplayName("噪音范围")]
        [NotifyParentProperty(true)]
        public float Amplitude { get; set; }

        public RandomValue(float @base, float amplitude)
        {
            this.Base = @base;
            this.Amplitude = amplitude;
        }
        public override string ToString()
        {
            return string.Format("{0}土{1}", Base, Amplitude);
        }

        public override object Clone()
        {
            return new RandomValue(Base, Amplitude);
        }
    }
    public class ControlPoint
    {
        [DisplayName("时间")]
        [NotifyParentProperty(true)]
        public float Time { get; set; }

        [DisplayName("值")]
        [NotifyParentProperty(true)]
        public float Value { get; set; }
        public ControlPoint()
        {
        }
        public ControlPoint(float time, float value)
        {
            this.Time = time;
            this.Value = value;
        }
        public override string ToString()
        {
            return string.Format("f({0:n}) = {1}", Time, Value);
        }
    }
    public class CurvedLinearValue : DynamicValue
    {
        [DisplayName("控制点")]
        public ControlPoint[] ControlPoints { get; set; }
        public override string ToString()
        {
            return "线性插值";
        }

        public override object Clone()
        {
            CurvedLinearValue ret = new CurvedLinearValue();
            List<ControlPoint> cps = new List<ControlPoint>();
            foreach (ControlPoint cp in this.ControlPoints)
            {
                cps.Add(new ControlPoint(cp.Time, cp.Value));
            }
            return ret;
        }
    }
    public class CurvedSplineValue : DynamicValue
    {
        [DisplayName("控制点")]
        public ControlPoint[] ControlPoints { get; set; }
        public override string ToString()
        {
            return "样条插值";
        }
        public override object Clone()
        {
            CurvedLinearValue ret = new CurvedLinearValue();
            List<ControlPoint> cps = new List<ControlPoint>();
            foreach (ControlPoint cp in this.ControlPoints)
            {
                cps.Add(new ControlPoint(cp.Time, cp.Value));
            }
            return ret;
        }
    }
    [TypeConverter(typeof(NamedEnumConverter<OscillateType>))]
    public enum OscillateType
    {
        [FieldAlias("正弦")]
        Sine,
        [FieldAlias("方波")]
        Square
    }
    public class OscillateValue : DynamicValue
    {
        [NotifyParentProperty(true)]
        [DisplayName("频率")]
        public float Frequency { get; set; }


        [NotifyParentProperty(true)]
        [DisplayName("偏移")]
        public float Base { get; set; }


        [NotifyParentProperty(true)]
        [DisplayName("振幅")]
        public float Amplitude { get; set; }


        [NotifyParentProperty(true)]
        [DisplayName("相位")]
        public float Phase { get; set; }

        [NotifyParentProperty(true)]
        [DisplayName("波形函数")]
        public OscillateType Type { get; set; }


        public override string ToString()
        {
            string f = Type == OscillateType.Sine ? "sin" : "square";
            StringBuilder sb = new StringBuilder();
            sb.Append("y=");
            if (Amplitude != 0)
            {
                if (Amplitude != 1)
                    sb.Append(Amplitude + "*");
                sb.Append(f);
                sb.Append("(");
                if (Frequency != 0)
                {
                    if (Frequency != 1)
                        sb.Append(Frequency + "*");
                    sb.Append("x");
                }
                if (Phase != 0)
                {
                    if (Frequency != 0)
                        sb.Append("+");
                    sb.Append(Phase);
                }
                if (Phase == 0 && Frequency == 0)
                    sb.Append("0");
                sb.Append(")");
            }
            if (Base != 0)
            {
                if (Amplitude != 0)
                    sb.Append("+");
                sb.Append(Base);
            }
            if (Amplitude == 0 && Base == 0)
                sb.Append("0");
            return sb.ToString();
        }

        public override object Clone()
        {
            return new OscillateValue
            {
                Frequency = this.Frequency,
                Base = this.Base,
                Phase = this.Phase,
                Amplitude = this.Amplitude,
                Type = this.Type
            };
        }
    }
    

}
